package com.trusfort.redis;

import redis.clients.jedis.*;
import redis.clients.jedis.params.ScanParams;
import redis.clients.jedis.resps.ScanResult;

import java.util.*;

/**
 * @author
 * @date
 * @desc 对Jedis进行了封装，在每次操作之后都将连接返回连接池，以防止连接没有及时回收导致的连接枯竭的问题
 * 
 * */
public class JedisClient {
	private DBIndex dbindex	= DBIndex.XDID_DB_INDEX;

	private static final String ERR_MSG = "Redis Error";
	public JedisClient() {

	}
	public JedisClient(DBIndex index) {
		this.dbindex = index;
	}
	
	
	public JedisClient(String host,String port,String passwd) {
		 
//		return ;
	}
	

	/*
	 * 删除关键值参数
	 */
	public long del(final String keys) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.del(keys);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}

	/*
	 * 设置关键值参数
	 */
	public void set(final String key, String value) throws RedisException {
		set(key,value,-1);
	}
	public void set(final String key, String value, int seconds) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			jedis.set(key, value);
			if(seconds!=-1){
				jedis.expire(key, seconds);
			}
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}


	/*
	 * 获取有关指定键的值
	 */
	public String get(final String key) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.get(key);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}

	}
	
	public ScanResult<String> scan(DBIndex dbIndex, final String key,String cursor,Integer count) {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbIndex);

			ScanParams scanParams=new ScanParams();
			scanParams.count(count);
			//DBIndex.XDID_DB_INDEX, pattern, cursor, 100000
			
			//使用sscan命令获取500条数据，使用cursor游标记录位置，下次循环使用
			return jedis.scan(cursor, scanParams);

		} catch (Exception e) {
			e.printStackTrace();
//			log.error("{}", ERR_MSG, e);
			return null;
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}
	
	

	/*
	 * 添加关键字hash值
	 */
	public void hmset(final String key, final Map<String, String> hash) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			jedis.hmset(key, hash);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}

	}

	public List<String> hmget(final String key, String ... fields) throws RedisException {
        Jedis jedis = null;
        try {
            jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.hmget(key, fields);
        } catch (Exception e) {
			throw new RedisException(e);
        } finally {
            RedisConnectionPool.getInstance().returnResource(jedis);
        }
    }

	/*
	 * 获取关键字hash值
	 */
	public Map<String, String> hgetAll(final String key) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.hgetAll(key);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}

	/*
	 * 为一个set Key添加一个值。 成功返回1， 如果这个值已经在这个Key中，则返回0。
	 */
	public Long sadd(final String key, final String ... members) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.sadd(key, members);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}


	public Set<String> sunion(String ... keys) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.sunion(keys);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}




	public Set<String> getSmemberValues(List<String> list) throws RedisException {

		Set<String> result = new HashSet<>();
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			Pipeline pipeline = jedis.pipelined();

			//管道返回的结果集
			List<Response<Set<String>>> searchResult = new ArrayList<>();
			for(String key:list){
				searchResult.add(pipeline.smembers(key));
			}
			pipeline.sync();
			if (!searchResult.isEmpty()){
				for (Response<Set<String>> keyResult:searchResult) {
					//从结果集中获取需要的value的数据
					result.addAll(keyResult.get());
				}
			}

			return result;
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}

	/*
	 * sMembers, sGetMembers描述：返回集合的内容
	 */
	public Set<String> smembers(final String key) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.smembers(key);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}


	/*
	 * 删除set Key中指定的value值 1 if the new element was removed 0 if the new element
	 * was not a member of the set
	 */
	public Long srem(final String key, final String members) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.srem(key, members);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}

	 

	/*
	 * 获取set 大小
	 */
	public Long scard(final String key) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.scard(key);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}


	public Map<String,Long> scard(final List<String> keys) throws RedisException {

		Map<String,Long> result = new HashMap<>();

		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);

			Pipeline pipeline = jedis.pipelined();

			List<Response<Long>> searchResult = new ArrayList<>();
			for(String key:keys){
				searchResult.add(pipeline.scard(key));
			}
			pipeline.sync();
			if (!searchResult.isEmpty()){
				for(int i=0;i<keys.size();i++){
					Response<Long> card = searchResult.get(i);
					result.put(keys.get(i),card.get());
				}
			}
			return result;
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}
	/*
	 * redis list rpush 由列表尾部添加字符串值。如果不存在该键则创建该列表。如果该键存在，而且不是一个列表，返回FALSE。
	 */
	public Long rpush(final String key, final String ... members) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.rpush(key, members);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}

	/**
	 * redis list lpush 由列表头部添加字符串值。 如果不存在该键则创建该列表。 如果该键存在，而且不是一个列表，返回FALSE。
	 **/
	public Long lpush(final String key, final String ... members) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.lpush(key, members);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}



	/*
	 * redis list llen 返回的列表的大小。如果列表不存在或为空，该命令返回0。如果该键不是列表，该命令返回FALSE。
	 */
	public Long llen(final String key) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.llen(key);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}



	/*
	 * redis incr 将 key 中储存的数字值增一。 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCR 操作。
	 * 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
	 */
	public Long incr(final String key) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.incr(key);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}

	/*
	 * 设置超时时间
	 */
	public Long expire(final String key, int second) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.expire(key, second);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}

	/*
	 * 删除list Key中指定的value值 count = 0 删除list中所有值为value的元素，
	 * count为负数，从尾到头删除第一个value元素，count为正数则从头到尾删除第一个value元素 返回值：成功删除的元素个数.
	 */
	public Long lrem(final String key, long count, final String members) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.lrem(key, count, members);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}


	/**
	 * 查看剩余生存时间
	 * 
	 * @param key
	 * @return
	 */
	public Long ttl(final String key) throws RedisException {
		Jedis jedis = null;
		try {
			jedis = RedisConnectionPool.getInstance().getJedis(dbindex);
			return jedis.ttl(key);
		} catch (Exception e) {
			throw new RedisException(e);
		} finally {
			RedisConnectionPool.getInstance().returnResource(jedis);
		}
	}
}
